// token守卫认证

import { CanActivate, ExecutionContext, UnauthorizedException ,Injectable} from "@nestjs/common";
import Config from '@/config';
import * as jwt from 'jsonwebtoken';
import { Reflector } from '@nestjs/core';
import { BaseDao } from '@/common/baseDao/base.service';


@Injectable()
export class AuthGuard implements CanActivate {

    constructor(
        private readonly reflector: Reflector,
        private readonly baseDao: BaseDao
    ){}

    async canActivate(context: ExecutionContext): Promise<boolean> {
       
        const request: Request = context.switchToHttp().getRequest();
        const token = request.headers[Config['authorization']];

        const handler = context.getHandler();
        const controller = context.getClass();
    
        // 获取方法的元数据，优先级高于控制器的元数据
        const isPublicMethod = this.reflector.get<boolean>('isNoAuth', handler);
        const isPublicController = this.reflector.get<boolean>('isNoAuth', controller);

        // console.log('isNoAuth',context.getClass())
        // 如果装饰带有isNoAuth 那么可以忽略token认证
        if (isPublicMethod || isPublicController) {
            return true; // 忽略认证
        }

        try {
            // 假设这是你的 token 验证逻辑
            const tokenInfo = this.validateToken(token);
            const {userId} = tokenInfo;
            if(userId){
                const userInfo = await this.baseDao.findById({
                    dbName:'quick-users',
                    id:userId
                })
                
                if(!userInfo)  throw new UnauthorizedException('身份认证已过期'!);
                request['userInfo'] = userInfo;
                return true;
            }else{
                throw new UnauthorizedException('无效token');
            }
        } catch (error) {
            throw new UnauthorizedException('身份认证已过期'!);
        }
        
    }

    validateToken(token: string) {
        try {
            const decoded = jwt.verify(token, Config['tokenSecret']); // 替换为你的密钥
            return decoded;
        } catch (error) {
            return false;
        }
    }
}